home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 August (Alt) / CHIP 2005-08.1.iso / program / guvenlik / syslinux-3.07.exe / ldlinux.asm < prev    next >
Encoding:
Assembly Source File  |  2005-01-07  |  36.9 KB  |  1,538 lines

  1. ; -*- fundamental -*- (asm-mode sucks)
  2. ; $Id: ldlinux.asm,v 1.180 2005/01/08 00:58:57 hpa Exp $
  3. ; ****************************************************************************
  4. ;
  5. ;  ldlinux.asm
  6. ;
  7. ;  A program to boot Linux kernels off an MS-DOS formatted floppy disk.     This
  8. ;  functionality is good to have for installation floppies, where it may
  9. ;  be hard to find a functional Linux system to run LILO off.
  10. ;
  11. ;  This program allows manipulation of the disk to take place entirely
  12. ;  from MS-LOSS, and can be especially useful in conjunction with the
  13. ;  umsdos filesystem.
  14. ;
  15. ;   Copyright (C) 1994-2004  H. Peter Anvin
  16. ;
  17. ;  This program is free software; you can redistribute it and/or modify
  18. ;  it under the terms of the GNU General Public License as published by
  19. ;  the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  20. ;  Boston MA 02111-1307, USA; either version 2 of the License, or
  21. ;  (at your option) any later version; incorporated herein by reference.
  22. ; ****************************************************************************
  23.  
  24. %ifndef IS_MDSLINUX
  25. %define IS_SYSLINUX 1
  26. %endif
  27. %include "macros.inc"
  28. %include "config.inc"
  29. %include "kernel.inc"
  30. %include "bios.inc"
  31. %include "tracers.inc"
  32. %include "layout.inc"
  33. ;
  34. ; Some semi-configurable constants... change on your own risk.
  35. ;
  36. my_id        equ syslinux_id
  37. FILENAME_MAX_LG2 equ 4            ; log2(Max filename size Including final null)
  38. FILENAME_MAX    equ 11            ; Max mangled filename size
  39. NULLFILE    equ ' '            ; First char space == null filename
  40. NULLOFFSET    equ 0            ; Position in which to look
  41. retry_count    equ 6            ; How patient are we with the disk?
  42. %assign HIGHMEM_SLOP 0            ; Avoid this much memory near the top
  43. LDLINUX_MAGIC    equ 0x3eb202fe        ; A random number to identify ourselves with
  44.  
  45. MAX_OPEN_LG2    equ 6            ; log2(Max number of open files)
  46. MAX_OPEN    equ (1 << MAX_OPEN_LG2)
  47.  
  48. SECTOR_SHIFT    equ 9
  49. SECTOR_SIZE    equ (1 << SECTOR_SHIFT)
  50.  
  51. ;
  52. ; This is what we need to do when idle
  53. ;
  54. %macro    RESET_IDLE 0
  55.     ; Nothing
  56. %endmacro
  57. %macro    DO_IDLE 0
  58.     ; Nothing
  59. %endmacro
  60.  
  61. ;
  62. ; The following structure is used for "virtual kernels"; i.e. LILO-style
  63. ; option labels.  The options we permit here are `kernel' and `append
  64. ; Since there is no room in the bottom 64K for all of these, we
  65. ; stick them at vk_seg:0000 and copy them down before we need them.
  66. ;
  67.         struc vkernel
  68. vk_vname:    resb FILENAME_MAX    ; Virtual name **MUST BE FIRST!**
  69. vk_rname:    resb FILENAME_MAX    ; Real name
  70. vk_appendlen:    resw 1
  71.         alignb 4
  72. vk_append:    resb max_cmd_len+1    ; Command line
  73.         alignb 4
  74. vk_end:        equ $            ; Should be <= vk_size
  75.         endstruc
  76.  
  77. ;
  78. ; Segment assignments in the bottom 640K
  79. ; Stick to the low 512K in case we're using something like M-systems flash
  80. ; which load a driver into low RAM (evil!!)
  81. ;
  82. ; 0000h - main code/data segment (and BIOS segment)
  83. ;
  84. real_mode_seg    equ 4000h
  85. cache_seg    equ 3000h        ; 64K area for metadata cache
  86. vk_seg          equ 2000h        ; Virtual kernels
  87. xfer_buf_seg    equ 1000h        ; Bounce buffer for I/O to high mem
  88. comboot_seg    equ real_mode_seg    ; COMBOOT image loading zone
  89.  
  90. ;
  91. ; File structure.  This holds the information for each currently open file.
  92. ;
  93.         struc open_file_t
  94. file_sector    resd 1            ; Sector pointer (0 = structure free)
  95. file_left    resd 1            ; Number of sectors left
  96.         endstruc
  97.  
  98. %ifndef DEPEND
  99. %if (open_file_t_size & (open_file_t_size-1))
  100. %error "open_file_t is not a power of 2"
  101. %endif
  102. %endif
  103.  
  104. ; ---------------------------------------------------------------------------
  105. ;   BEGIN CODE
  106. ; ---------------------------------------------------------------------------
  107.  
  108. ;
  109. ; Memory below this point is reserved for the BIOS and the MBR
  110. ;
  111.         section .earlybss
  112. trackbufsize    equ 8192
  113. trackbuf    resb trackbufsize    ; Track buffer goes here
  114. getcbuf        resb trackbufsize
  115.         ; ends at 4800h
  116.  
  117.         section .bss
  118.         alignb 8
  119.  
  120.         ; Expanded superblock
  121. SuperInfo    equ $
  122.         resq 16            ; The first 16 bytes expanded 8 times
  123. FAT        resd 1            ; Location of (first) FAT
  124. RootDirArea    resd 1            ; Location of root directory area
  125. RootDir        resd 1            ; Location of root directory proper
  126. DataArea    resd 1            ; Location of data area
  127. RootDirSize    resd 1            ; Root dir size in sectors
  128. TotalSectors    resd 1            ; Total number of sectors
  129. EndSector    resd 1            ; Location of filesystem end
  130. ClustSize    resd 1            ; Bytes/cluster
  131. ClustMask    resd 1            ; Sectors/cluster - 1
  132. CopySuper    resb 1            ; Distinguish .bs versus .bss
  133. DriveNumber    resb 1            ; BIOS drive number
  134. ClustShift    resb 1            ; Shift count for sectors/cluster
  135. ClustByteShift    resb 1            ; Shift count for bytes/cluster
  136.  
  137.         alignb open_file_t_size
  138. Files        resb MAX_OPEN*open_file_t_size
  139.  
  140. ;
  141. ; Constants for the xfer_buf_seg
  142. ;
  143. ; The xfer_buf_seg is also used to store message file buffers.  We
  144. ; need two trackbuffers (text and graphics), plus a work buffer
  145. ; for the graphics decompressor.
  146. ;
  147. xbs_textbuf    equ 0            ; Also hard-coded, do not change
  148. xbs_vgabuf    equ trackbufsize
  149. xbs_vgatmpbuf    equ 2*trackbufsize
  150.  
  151.  
  152.         section .text
  153. ;
  154. ; Some of the things that have to be saved very early are saved
  155. ; "close" to the initial stack pointer offset, in order to
  156. ; reduce the code size...
  157. ;
  158. StackBuf    equ $-44-32        ; Start the stack here (grow down - 4K)
  159. PartInfo    equ StackBuf        ; Saved partition table entry
  160. FloppyTable    equ PartInfo+16        ; Floppy info table (must follow PartInfo)
  161. OrigFDCTabPtr    equ StackBuf-4        ; The high dword on the stack
  162.  
  163. ;
  164. ; Primary entry point.  Tempting as though it may be, we can't put the
  165. ; initial "cli" here; the jmp opcode in the first byte is part of the
  166. ; "magic number" (using the term very loosely) for the DOS superblock.
  167. ;
  168. bootsec        equ $
  169.         jmp short start        ; 2 bytes
  170.         nop            ; 1 byte
  171. ;
  172. ; "Superblock" follows -- it's in the boot sector, so it's already
  173. ; loaded and ready for us
  174. ;
  175. bsOemName    db 'SYSLINUX'        ; The SYS command sets this, so...
  176. ;
  177. ; These are the fields we actually care about.  We end up expanding them
  178. ; all to dword size early in the code, so generate labels for both
  179. ; the expanded and unexpanded versions.
  180. ;
  181. %macro        superb 1
  182. bx %+ %1    equ SuperInfo+($-superblock)*8+4
  183. bs %+ %1    equ $
  184.         zb 1
  185. %endmacro
  186. %macro        superw 1
  187. bx %+ %1    equ SuperInfo+($-superblock)*8
  188. bs %+ %1    equ $
  189.         zw 1
  190. %endmacro
  191. %macro        superd 1
  192. bx %+ %1    equ $            ; no expansion for dwords
  193. bs %+ %1    equ $
  194.         zd 1
  195. %endmacro
  196. superblock    equ $
  197.         superw BytesPerSec
  198.         superb SecPerClust
  199.         superw ResSectors
  200.         superb FATs
  201.         superw RootDirEnts
  202.         superw Sectors
  203.         superb Media
  204.         superw FATsecs
  205.         superw SecPerTrack
  206.         superw Heads
  207. superinfo_size    equ ($-superblock)-1    ; How much to expand
  208.         superd Hidden
  209.         superd HugeSectors
  210.         ;
  211.         ; This is as far as FAT12/16 and FAT32 are consistent
  212.         ;
  213.         zb 54            ; FAT12/16 need 26 more bytes,
  214.                     ; FAT32 need 54 more bytes
  215. superblock_len    equ $-superblock
  216.  
  217. SecPerClust    equ bxSecPerClust
  218. ;
  219. ; Note we don't check the constraints above now; we did that at install
  220. ; time (we hope!)
  221. ;
  222. start:
  223.         cli            ; No interrupts yet, please
  224.         cld            ; Copy upwards
  225. ;
  226. ; Set up the stack
  227. ;
  228.         xor ax,ax
  229.         mov ss,ax
  230.         mov sp,StackBuf        ; Just below BSS
  231.         mov es,ax
  232. ;
  233. ; DS:SI may contain a partition table entry.  Preserve it for us.
  234. ;
  235.         mov cx,8        ; Save partition info
  236.         mov di,sp
  237.         rep movsw
  238.  
  239.         mov ds,ax        ; Now we can initialize DS...
  240.  
  241. ;
  242. ; Now sautee the BIOS floppy info block to that it will support decent-
  243. ; size transfers; the floppy block is 11 bytes and is stored in the
  244. ; INT 1Eh vector (brilliant waste of resources, eh?)
  245. ;
  246. ; Of course, if BIOSes had been properly programmed, we wouldn't have
  247. ; had to waste precious space with this code.
  248. ;
  249.         mov bx,fdctab
  250.         lfs si,[bx]        ; FS:SI -> original fdctab
  251.         push fs            ; Save on stack in case we need to bail
  252.         push si
  253.  
  254.         ; Save the old fdctab even if hard disk so the stack layout
  255.         ; is the same.  The instructions above do not change the flags
  256.         mov [DriveNumber],dl    ; Save drive number in DL
  257.         and dl,dl        ; If floppy disk (00-7F), assume no
  258.                     ; partition table
  259.         js harddisk
  260.  
  261. floppy:
  262.         mov cl,6        ; 12 bytes (CX == 0)
  263.         ; es:di -> FloppyTable already
  264.         ; This should be safe to do now, interrupts are off...
  265.         mov [bx],di        ; FloppyTable
  266.         mov [bx+2],ax        ; Segment 0
  267.         fs rep movsw        ; Faster to move words
  268.         mov cl,[bsSecPerTrack]  ; Patch the sector count
  269.         mov [di-8],cl
  270.         ; AX == 0 here
  271.         int 13h            ; Some BIOSes need this
  272.  
  273.         jmp short not_harddisk
  274. ;
  275. ; The drive number and possibly partition information was passed to us
  276. ; by the BIOS or previous boot loader (MBR).  Current "best practice" is to
  277. ; trust that rather than what the superblock contains.
  278. ;
  279. ; Would it be better to zero out bsHidden if we don't have a partition table?
  280. ;
  281. ; Note: di points to beyond the end of PartInfo
  282. ;
  283. harddisk:
  284.         test byte [di-16],7Fh    ; Sanity check: "active flag" should
  285.         jnz no_partition    ; be 00 or 80
  286.         mov eax,[di-8]        ; Partition offset (dword)
  287.         mov [bsHidden],eax
  288. no_partition:
  289. ;
  290. ; Get disk drive parameters (don't trust the superblock.)  Don't do this for
  291. ; floppy drives -- INT 13:08 on floppy drives will (may?) return info about
  292. ; what the *drive* supports, not about the *media*.  Fortunately floppy disks
  293. ; tend to have a fixed, well-defined geometry which is stored in the superblock.
  294. ;
  295.         ; DL == drive # still
  296.         mov ah,08h
  297.         int 13h
  298.         jc no_driveparm
  299.         and ah,ah
  300.         jnz no_driveparm
  301.         shr dx,8
  302.         inc dx            ; Contains # of heads - 1
  303.         mov [bsHeads],dx
  304.         and cx,3fh
  305.         mov [bsSecPerTrack],cx
  306. no_driveparm:
  307. not_harddisk:
  308. ;
  309. ; Ready to enable interrupts, captain
  310. ;
  311.         sti
  312.  
  313.  
  314. ;
  315. ; Do we have EBIOS (EDD)?
  316. ;
  317. eddcheck:
  318.         mov bx,55AAh
  319.         mov ah,41h        ; EDD existence query
  320.         mov dl,[DriveNumber]
  321.         int 13h
  322.         jc .noedd
  323.         cmp bx,0AA55h
  324.         jne .noedd
  325.         test cl,1        ; Extended disk access functionality set
  326.         jz .noedd
  327.         ;
  328.         ; We have EDD support...
  329.         ;
  330.         mov byte [getlinsec.jmp+1],getlinsec_ebios-(getlinsec.jmp+2)
  331. .noedd:
  332.  
  333. ;
  334. ; Load the first sector of LDLINUX.SYS; this used to be all proper
  335. ; with parsing the superblock and root directory; it doesn't fit
  336. ; together with EBIOS support, unfortunately.
  337. ;
  338.         mov eax,[FirstSector]    ; Sector start
  339.         mov bx,ldlinux_sys    ; Where to load it
  340.         call getonesec
  341.         
  342.         ; Some modicum of integrity checking
  343.         cmp dword [ldlinux_magic],LDLINUX_MAGIC
  344.         jne kaboom
  345.         cmp dword [ldlinux_magic+4],HEXDATE
  346.         jne kaboom
  347.  
  348.         ; Go for it...
  349.         jmp ldlinux_ent
  350.  
  351. ;
  352. ; kaboom: write a message and bail out.
  353. ;
  354. kaboom:
  355.         xor si,si
  356.         mov ss,si        
  357.         mov sp,StackBuf-4     ; Reset stack
  358.         mov ds,si        ; Reset data segment
  359.         pop dword [fdctab]    ; Restore FDC table
  360. .patch:        mov si,bailmsg
  361.         call writestr        ; Returns with AL = 0
  362.         cbw            ; AH <- 0
  363.         int 16h            ; Wait for keypress
  364.         int 19h            ; And try once more to boot...
  365. .norge:        jmp short .norge    ; If int 19h returned; this is the end
  366.  
  367. ;
  368. ;
  369. ; writestr: write a null-terminated string to the console
  370. ;        This assumes we're on page 0.  This is only used for early
  371. ;           messages, so it should be OK.
  372. ;
  373. writestr:
  374. .loop:        lodsb
  375.         and al,al
  376.                 jz .return
  377.         mov ah,0Eh        ; Write to screen as TTY
  378.         mov bx,0007h        ; Attribute
  379.         int 10h
  380.         jmp short .loop
  381. .return:    ret
  382.  
  383. ;
  384. ; xint13: wrapper for int 13h which will retry 6 times and then die,
  385. ;      AND save all registers except BP
  386. ;
  387. xint13:
  388. .again:
  389.                 mov bp,retry_count
  390. .loop:          pushad
  391.                 int 13h
  392.                 popad
  393.                 jnc writestr.return
  394.                 dec bp
  395.                 jnz .loop
  396. .disk_error:
  397.         jmp strict near kaboom    ; Patched
  398.  
  399.  
  400. ;
  401. ; getonesec: get one disk sector
  402. ;
  403. getonesec:
  404.         mov bp,1        ; One sector
  405.         ; Fall through
  406.  
  407. ;
  408. ; getlinsec: load a sequence of BP floppy sector given by the linear sector
  409. ;         number in EAX into the buffer at ES:BX.  We try to optimize
  410. ;         by loading up to a whole track at a time, but the user
  411. ;         is responsible for not crossing a 64K boundary.
  412. ;         (Yes, BP is weird for a count, but it was available...)
  413. ;
  414. ;         On return, BX points to the first byte after the transferred
  415. ;         block.
  416. ;
  417. ;            This routine assumes CS == DS, and trashes most registers.
  418. ;
  419. ; Stylistic note: use "xchg" instead of "mov" when the source is a register
  420. ; that is dead from that point; this saves space.  However, please keep
  421. ; the order to dst,src to keep things sane.
  422. ;
  423. getlinsec:
  424.         add eax,[bsHidden]        ; Add partition offset
  425. .jmp:        jmp strict short getlinsec_cbios    ; This is patched
  426.  
  427. ;
  428. ; getlinsec_ebios:
  429. ;
  430. ; getlinsec implementation for EBIOS (EDD)
  431. ;
  432. getlinsec_ebios:
  433.                 mov si,dapa                     ; Load up the DAPA
  434.                 mov [si+4],bx
  435.                 mov [si+6],es
  436.                 mov [si+8],eax
  437. .loop:
  438.                 push bp                         ; Sectors left
  439.         call maxtrans            ; Enforce maximum transfer size
  440. .bp_ok:
  441.                 mov [si+2],bp
  442.                 mov dl,[DriveNumber]
  443.                 mov ah,42h                      ; Extended Read
  444.                 call xint13
  445.                 pop bp
  446.                 movzx eax,word [si+2]           ; Sectors we read
  447.                 add [si+8],eax                  ; Advance sector pointer
  448.                 sub bp,ax                       ; Sectors left
  449.                 shl ax,9                        ; 512-byte sectors
  450.                 add [si+4],ax                   ; Advance buffer pointer
  451.                 and bp,bp
  452.                 jnz .loop
  453.                 mov eax,[si+8]                  ; Next sector
  454.                 mov bx,[si+4]                   ; Buffer pointer
  455.                 ret
  456.  
  457. ;
  458. ; getlinsec_cbios:
  459. ;
  460. ; getlinsec implementation for legacy CBIOS
  461. ;
  462. getlinsec_cbios:
  463. .loop:
  464.         push eax
  465.         push bp
  466.         push bx
  467.  
  468.         movzx esi,word [bsSecPerTrack]
  469.         movzx edi,word [bsHeads]
  470.         ;
  471.         ; Dividing by sectors to get (track,sector): we may have
  472.         ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
  473.         ;
  474.         xor edx,edx        ; Zero-extend LBA to 64 bits
  475.         div esi
  476.         xor cx,cx
  477.         xchg cx,dx        ; CX <- sector index (0-based)
  478.                     ; EDX <- 0
  479.         ; eax = track #
  480.         div edi            ; Convert track to head/cyl
  481.         ;
  482.         ; Now we have AX = cyl, DX = head, CX = sector (0-based),
  483.         ; BP = sectors to transfer, SI = bsSecPerTrack,
  484.         ; ES:BX = data target
  485.         ;
  486.  
  487.         call maxtrans            ; Enforce maximum transfer size
  488.  
  489.         ; Must not cross track boundaries, so BP <= SI-CX
  490.         sub si,cx
  491.         cmp bp,si
  492.         jna .bp_ok
  493.         mov bp,si
  494. .bp_ok:    
  495.  
  496.         shl ah,6        ; Because IBM was STOOPID
  497.                     ; and thought 8 bits were enough
  498.                     ; then thought 10 bits were enough...
  499.         inc cx            ; Sector numbers are 1-based, sigh
  500.         or cl,ah
  501.         mov ch,al
  502.         mov dh,dl
  503.         mov dl,[DriveNumber]
  504.         xchg ax,bp        ; Sector to transfer count
  505.         mov ah,02h        ; Read sectors
  506.         call xint13
  507.         movzx ecx,al
  508.         shl ax,9        ; Convert sectors in AL to bytes in AX
  509.         pop bx
  510.         add bx,ax
  511.         pop bp
  512.         pop eax
  513.         add eax,ecx
  514.         sub bp,cx
  515.         jnz .loop
  516.         ret
  517.  
  518. ;
  519. ; Truncate BP to MaxTransfer
  520. ;
  521. maxtrans:
  522.         cmp bp,[MaxTransfer]
  523.         jna .ok
  524.         mov bp,[MaxTransfer]
  525. .ok:        ret
  526.  
  527. ;
  528. ; Error message on failure
  529. ;
  530. bailmsg:    db 'Boot failed', 0Dh, 0Ah, 0
  531.  
  532. ;
  533. ; EBIOS disk address packet
  534. ;
  535.         align 4, db 0
  536. dapa:
  537.                 dw 16                           ; Packet size
  538. .count:         dw 0                            ; Block count
  539. .off:           dw 0                            ; Offset of buffer
  540. .seg:           dw 0                            ; Segment of buffer
  541. .lba:           dd 0                            ; LBA (LSW)
  542.                 dd 0                            ; LBA (MSW)
  543.  
  544.  
  545. %if 1
  546. bs_checkpt_off    equ ($-$$)
  547. %ifndef DEPEND
  548. %if bs_checkpt_off > 1F8h
  549. %error "Boot sector overflow"
  550. %endif
  551. %endif
  552.  
  553.         zb 1F8h-($-$$)
  554. %endif
  555. FirstSector    dd 0xDEADBEEF            ; Location of sector 1
  556. MaxTransfer    dw 0x007F            ; Max transfer size
  557. bootsignature    dw 0AA55h
  558.  
  559. ;
  560. ; ===========================================================================
  561. ;  End of boot sector
  562. ; ===========================================================================
  563. ;  Start of LDLINUX.SYS
  564. ; ===========================================================================
  565.  
  566. ldlinux_sys:
  567.  
  568. syslinux_banner    db 0Dh, 0Ah
  569. %if IS_MDSLINUX
  570.         db 'MDSLINUX '
  571. %else
  572.         db 'SYSLINUX '
  573. %endif
  574.         db version_str, ' ', date, ' ', 0
  575.         db 0Dh, 0Ah, 1Ah    ; EOF if we "type" this in DOS
  576.  
  577.         align 8, db 0
  578. ldlinux_magic    dd LDLINUX_MAGIC
  579.         dd HEXDATE
  580.  
  581. ;
  582. ; This area is patched by the installer.  It is found by looking for
  583. ; LDLINUX_MAGIC, plus 8 bytes.
  584. ;
  585. patch_area:
  586. LDLDwords    dw 0        ; Total dwords starting at ldlinux_sys
  587. LDLSectors    dw 0        ; Number of sectors - (bootsec+this sec)
  588. CheckSum    dd 0        ; Checksum starting at ldlinux_sys
  589.                 ; value = LDLINUX_MAGIC - [sum of dwords]
  590.  
  591. ; Space for up to 64 sectors, the theoretical maximum
  592. SectorPtrs    times 64 dd 0
  593.  
  594. ldlinux_ent:
  595. ; Note that some BIOSes are buggy and run the boot sector at 07C0:0000
  596. ; instead of 0000:7C00 and the like.  We don't want to add anything
  597. ; more to the boot sector, so it is written to not assume a fixed
  598. ; value in CS, but we don't want to deal with that anymore from now
  599. ; on.
  600. ;
  601.         jmp 0:.next
  602. .next:
  603.  
  604. ;
  605. ; Tell the user we got this far
  606. ;
  607.         mov si,syslinux_banner
  608.         call writestr
  609.  
  610. ;
  611. ; Patch disk error handling
  612. ;
  613.         mov word [xint13.disk_error+1],do_disk_error-(xint13.disk_error+3)
  614.  
  615. ;
  616. ; Now we read the rest of LDLINUX.SYS.    Don't bother loading the first
  617. ; sector again, though.
  618. ;
  619. load_rest:
  620.         mov si,SectorPtrs
  621.         mov bx,7C00h+2*SECTOR_SIZE    ; Where we start loading
  622.         mov cx,[LDLSectors]
  623.  
  624. .get_chunk:
  625.         jcxz .done
  626.         xor bp,bp
  627.         lodsd                ; First sector of this chunk
  628.  
  629.         mov edx,eax
  630.  
  631. .make_chunk:
  632.         inc bp
  633.         dec cx
  634.         jz .chunk_ready
  635.         inc edx                ; Next linear sector
  636.         cmp [esi],edx            ; Does it match
  637.         jnz .chunk_ready        ; If not, this is it
  638.         add esi,4            ; If so, add sector to chunk
  639.         jmp short .make_chunk
  640.  
  641. .chunk_ready:
  642.         call getlinsecsr
  643.         shl bp,SECTOR_SHIFT
  644.         add bx,bp
  645.         jmp .get_chunk
  646.  
  647. .done:
  648.  
  649. ;
  650. ; All loaded up, verify that we got what we needed.
  651. ; Note: the checksum field is embedded in the checksum region, so
  652. ; by the time we get to the end it should all cancel out.
  653. ;
  654. verify_checksum:
  655.         mov si,ldlinux_sys
  656.         mov cx,[LDLDwords]
  657.         mov edx,-LDLINUX_MAGIC
  658. .checksum:
  659.         lodsd
  660.         add edx,eax
  661.         loop .checksum
  662.  
  663.         and edx,edx            ; Should be zero
  664.         jz all_read            ; We're cool, go for it!
  665.  
  666. ;
  667. ; Uh-oh, something went bad...
  668. ;
  669.         mov si,checksumerr_msg
  670.         call writestr
  671.         jmp kaboom
  672.  
  673. ;
  674. ; -----------------------------------------------------------------------------
  675. ; Subroutines that have to be in the first sector
  676. ; -----------------------------------------------------------------------------
  677.  
  678. ;
  679. ; getlinsecsr: save registers, call getlinsec, restore registers
  680. ;
  681. getlinsecsr:    pushad
  682.         call getlinsec
  683.         popad
  684.         ret
  685.  
  686. ;
  687. ; This routine captures disk errors, and tries to decide if it is
  688. ; time to reduce the transfer size.
  689. ;
  690. do_disk_error:
  691.         cmp ah,42h
  692.         je .ebios
  693.         shr al,1        ; Try reducing the transfer size
  694.         mov [MaxTransfer],al    
  695.         jz kaboom        ; If we can't, we're dead...
  696.         jmp xint13        ; Try again
  697. .ebios:
  698.         push ax
  699.         mov ax,[si+2]
  700.         shr ax,1
  701.         mov [MaxTransfer],ax
  702.         mov [si+2],ax
  703.         pop ax
  704.         jmp xint13
  705.  
  706. ;
  707. ; Checksum error message
  708. ;
  709. checksumerr_msg    db 'Load error - ', 0    ; Boot failed appended
  710.  
  711. ;
  712. ; Debug routine
  713. ;
  714. %ifdef debug
  715. safedumpregs:
  716.         cmp word [Debug_Magic],0D00Dh
  717.         jnz nc_return
  718.         jmp dumpregs
  719. %endif
  720.  
  721. rl_checkpt    equ $                ; Must be <= 8000h
  722.  
  723. rl_checkpt_off    equ ($-$$)
  724. %if 0 ; ndef DEPEND
  725. %if rl_checkpt_off > 400h
  726. %error "Sector 1 overflow"
  727. %endif
  728. %endif
  729.  
  730. ; ----------------------------------------------------------------------------
  731. ;  End of code and data that have to be in the first sector
  732. ; ----------------------------------------------------------------------------
  733.  
  734. all_read:
  735. ;
  736. ; Let the user (and programmer!) know we got this far.  This used to be
  737. ; in Sector 1, but makes a lot more sense here.
  738. ;
  739.         mov si,copyright_str
  740.         call writestr
  741.  
  742.  
  743. ;
  744. ; Insane hack to expand the superblock to dwords
  745. ;
  746. expand_super:
  747.         xor eax,eax
  748.         mov si,superblock
  749.         mov di,SuperInfo
  750.         mov cx,superinfo_size
  751. .loop:
  752.         lodsw
  753.         dec si
  754.         stosd                ; Store expanded word
  755.         xor ah,ah
  756.         stosd                ; Store expanded byte
  757.         loop .loop
  758.  
  759. ;
  760. ; Compute some information about this filesystem.
  761. ;
  762.  
  763. ; First, generate the map of regions
  764. genfatinfo:
  765.         mov edx,[bxSectors]
  766.         and dx,dx
  767.         jnz .have_secs
  768.         mov edx,[bsHugeSectors]
  769. .have_secs:
  770.         mov [TotalSectors],edx
  771.  
  772.         add edx,eax
  773.         mov [EndSector],edx
  774.  
  775.         mov eax,[bxResSectors]
  776.         mov [FAT],eax            ; Beginning of FAT
  777.         mov edx,[bxFATsecs]
  778.         and dx,dx
  779.         jnz .have_fatsecs
  780.         mov edx,[bootsec+36]        ; FAT32 BPB_FATsz32
  781. .have_fatsecs:
  782.         imul edx,[bxFATs]
  783.         add eax,edx
  784.         mov [RootDirArea],eax        ; Beginning of root directory
  785.         mov [RootDir],eax        ; For FAT12/16 == root dir location
  786.  
  787.         mov edx,[bxRootDirEnts]
  788.         add dx,SECTOR_SIZE/32-1
  789.         shr dx,SECTOR_SHIFT-5
  790.         mov [RootDirSize],edx
  791.         add eax,edx
  792.         mov [DataArea],eax        ; Beginning of data area
  793.  
  794. ; Next, generate a cluster size shift count and mask
  795.         mov eax,[bxSecPerClust]
  796.         bsr cx,ax
  797.         mov [ClustShift],cl
  798.         push cx
  799.         add cl,9
  800.         mov [ClustByteShift],cl
  801.         pop cx
  802.         dec ax
  803.         mov [ClustMask],eax
  804.         inc ax
  805.         shl eax,9
  806.         mov [ClustSize],eax
  807.  
  808. ;
  809. ; FAT12, FAT16 or FAT28^H^H32?  This computation is fscking ridiculous.
  810. ;
  811. getfattype:
  812.         mov eax,[EndSector]
  813.         sub eax,[DataArea]
  814.         shr eax,cl            ; cl == ClustShift
  815.         mov cl,nextcluster_fat12-(nextcluster+2)
  816.         cmp eax,4085            ; FAT12 limit
  817.         jb .setsize
  818.         mov cl,nextcluster_fat16-(nextcluster+2)
  819.         cmp eax,65525            ; FAT16 limit
  820.         jb .setsize
  821.         ;
  822.         ; FAT32, root directory is a cluster chain
  823.         ;
  824.         mov cl,[ClustShift]
  825.         mov eax,[bootsec+44]        ; Root directory cluster
  826.         sub eax,2
  827.         shl eax,cl
  828.         add eax,[DataArea]
  829.         mov [RootDir],eax
  830.         mov cl,nextcluster_fat28-(nextcluster+2)
  831. .setsize:
  832.         mov byte [nextcluster+1],cl
  833.  
  834. ;
  835. ; Common initialization code
  836. ;
  837. %include "cpuinit.inc"
  838. %include "init.inc"
  839.  
  840. ;
  841. ; Clear Files structures
  842. ;
  843.         mov di,Files
  844.         mov cx,(MAX_OPEN*open_file_t_size)/4
  845.         xor eax,eax
  846.         rep stosd
  847.  
  848. ;
  849. ; Initialize the metadata cache
  850. ;
  851.         call initcache
  852.  
  853. ;
  854. ; Now, everything is "up and running"... patch kaboom for more
  855. ; verbosity and using the full screen system
  856. ;
  857.         ; E9 = JMP NEAR
  858.         mov dword [kaboom.patch],0e9h+((kaboom2-(kaboom.patch+3)) << 8)
  859.  
  860. ;
  861. ; Now we're all set to start with our *real* business.    First load the
  862. ; configuration file (if any) and parse it.
  863. ;
  864. ; In previous versions I avoided using 32-bit registers because of a
  865. ; rumour some BIOSes clobbered the upper half of 32-bit registers at
  866. ; random.  I figure, though, that if there are any of those still left
  867. ; they probably won't be trying to install Linux on them...
  868. ;
  869. ; The code is still ripe with 16-bitisms, though.  Not worth the hassle
  870. ; to take'm out.  In fact, we may want to put them back if we're going
  871. ; to boot ELKS at some point.
  872. ;
  873.  
  874. ;
  875. ; Load configuration file
  876. ;
  877.         mov di,syslinux_cfg
  878.         call open
  879.         jz no_config_file
  880.  
  881. ;
  882. ; Now we have the config file open.  Parse the config file and
  883. ; run the user interface.
  884. ;
  885. %include "ui.inc"
  886.  
  887. ;
  888. ; Linux kernel loading code is common.
  889. ;
  890. %include "runkernel.inc"
  891.  
  892. ;
  893. ; COMBOOT-loading code
  894. ;
  895. %include "comboot.inc"
  896. %include "com32.inc"
  897. %include "cmdline.inc"
  898.  
  899. ;
  900. ; Boot sector loading code
  901. ;
  902. %include "bootsect.inc"
  903.  
  904. ;
  905. ; abort_check: let the user abort with <ESC> or <Ctrl-C>
  906. ;
  907. abort_check:
  908.         call pollchar
  909.         jz ac_ret1
  910.         pusha
  911.         call getchar
  912.         cmp al,27            ; <ESC>
  913.         je ac_kill
  914.         cmp al,3            ; <Ctrl-C>
  915.         jne ac_ret2
  916. ac_kill:    mov si,aborted_msg
  917.  
  918. ;
  919. ; abort_load: Called by various routines which wants to print a fatal
  920. ;             error message and return to the command prompt.  Since this
  921. ;             may happen at just about any stage of the boot process, assume
  922. ;             our state is messed up, and just reset the segment registers
  923. ;             and the stack forcibly.
  924. ;
  925. ;             SI    = offset (in _text) of error message to print
  926. ;
  927. abort_load:
  928.                 mov ax,cs                       ; Restore CS = DS = ES
  929.                 mov ds,ax
  930.                 mov es,ax
  931.                 cli
  932.                 mov sp,StackBuf-2*3            ; Reset stack
  933.                 mov ss,ax                       ; Just in case...
  934.                 sti
  935.                 call cwritestr                  ; Expects SI -> error msg
  936. al_ok:          jmp enter_command               ; Return to command prompt
  937. ;
  938. ; End of abort_check
  939. ;
  940. ac_ret2:    popa
  941. ac_ret1:    ret
  942.  
  943. ;
  944. ; allocate_file: Allocate a file structure
  945. ;
  946. ;        If successful:
  947. ;          ZF set
  948. ;          BX = file pointer
  949. ;        In unsuccessful:
  950. ;          ZF clear
  951. ;
  952. allocate_file:
  953.         TRACER 'a'
  954.         push cx
  955.         mov bx,Files
  956.         mov cx,MAX_OPEN
  957. .check:        cmp dword [bx], byte 0
  958.         je .found
  959.         add bx,open_file_t_size        ; ZF = 0
  960.         loop .check
  961.         ; ZF = 0 if we fell out of the loop
  962. .found:        pop cx
  963.         ret
  964.  
  965. ;
  966. ; searchdir:
  967. ;         Search the root directory for a pre-mangled filename in DS:DI.
  968. ;
  969. ;         NOTE: This file considers finding a zero-length file an
  970. ;         error.  This is so we don't have to deal with that special
  971. ;         case elsewhere in the program (most loops have the test
  972. ;         at the end).
  973. ;
  974. ;         If successful:
  975. ;        ZF clear
  976. ;        SI    = file pointer
  977. ;        DX:AX    = file length in bytes
  978. ;         If unsuccessful
  979. ;        ZF set
  980. ;
  981.  
  982. searchdir:
  983.         call allocate_file
  984.         jnz .alloc_failure
  985.  
  986.         push gs
  987.         push es
  988.         push ds
  989.         pop es                ; ES = DS
  990.  
  991.         mov eax,[RootDir]        ; First root directory sector
  992.  
  993. .scansector:
  994.         call getcachesector
  995.         ; GS:SI now points to this sector
  996.  
  997.         mov cx,SECTOR_SIZE/32        ; 32 == directory entry size
  998. .scanentry:
  999.         cmp byte [gs:si],0
  1000.         jz .failure            ; Hit directory high water mark
  1001.         push cx
  1002.         push si
  1003.         push di
  1004.         mov cx,11
  1005.         gs repe cmpsb
  1006.         pop di
  1007.         pop si
  1008.         pop cx
  1009.         jz .found
  1010.         add si,32
  1011.         loop .scanentry
  1012.  
  1013.         call nextsector
  1014.         jnc .scansector            ; CF is set if we're at end
  1015.  
  1016.         ; If we get here, we failed
  1017. .failure:
  1018.         pop es
  1019.         pop gs
  1020. .alloc_failure:
  1021.         xor ax,ax            ; ZF <- 1
  1022.         ret
  1023. .found:
  1024.         mov eax,[gs:si+28]        ; File size
  1025.         add eax,SECTOR_SIZE-1
  1026.         shr eax,SECTOR_SHIFT
  1027.         jz .failure            ; Zero-length file
  1028.         mov [bx+4],eax
  1029.  
  1030.         mov cl,[ClustShift]
  1031.         mov dx,[gs:si+20]        ; High cluster word
  1032.         shl edx,16
  1033.         mov dx,[gs:si+26]        ; Low cluster word
  1034.         sub edx,2
  1035.         shl edx,cl
  1036.         add edx,[DataArea]
  1037.         mov [bx],edx            ; Starting sector
  1038.  
  1039.         mov eax,[gs:si+28]        ; File length again
  1040.         mov dx,[gs:si+30]        ; 16-bitism, sigh
  1041.         mov si,bx
  1042.         and eax,eax            ; ZF <- 0
  1043.  
  1044.         pop es
  1045.         pop gs
  1046.         ret
  1047.  
  1048. ;
  1049. ; writechr:    Write a single character in AL to the console without
  1050. ;        mangling any registers; handle video pages correctly.
  1051. ;
  1052. writechr:
  1053.         call write_serial    ; write to serial port if needed
  1054.         pushfd
  1055.         test byte [cs:DisplayCon], 01h
  1056.         jz .nothing
  1057.         pushad
  1058.         mov ah,0Eh
  1059.         mov bl,07h        ; attribute
  1060.         mov bh,[cs:BIOS_page]    ; current page
  1061.         int 10h
  1062.         popad
  1063. .nothing:
  1064.         popfd
  1065.         ret
  1066.  
  1067. ;
  1068. ;
  1069. ; kaboom2: once everything is loaded, replace the part of kaboom
  1070. ;       starting with "kaboom.patch" with this part
  1071.  
  1072. kaboom2:
  1073.         mov si,err_bootfailed
  1074.         call cwritestr
  1075.         call getchar
  1076.         call vgaclearmode
  1077.         int 19h            ; And try once more to boot...
  1078. .norge:        jmp short .norge    ; If int 19h returned; this is the end
  1079.  
  1080. ;
  1081. ; mangle_name: Mangle a DOS filename pointed to by DS:SI into a buffer pointed
  1082. ;           to by ES:DI; ends on encountering any whitespace
  1083. ;
  1084.  
  1085. mangle_name:
  1086.         mov cx,11            ; # of bytes to write
  1087. mn_loop:
  1088.         lodsb
  1089.         cmp al,' '            ; If control or space, end
  1090.         jna mn_end
  1091.         cmp al,'.'            ; Period -> space-fill
  1092.         je mn_is_period
  1093.         cmp al,'a'
  1094.         jb mn_not_lower
  1095.         cmp al,'z'
  1096.         ja mn_not_uslower
  1097.         sub al,020h
  1098.         jmp short mn_not_lower
  1099. mn_is_period:    mov al,' '            ; We need to space-fill
  1100. mn_period_loop: cmp cx,3            ; If <= 3 characters left
  1101.         jbe mn_loop            ; Just ignore it
  1102.         stosb                ; Otherwise, write a period
  1103.         loop mn_period_loop        ; Dec CX and (always) jump
  1104. mn_not_uslower: cmp al,ucase_low
  1105.         jb mn_not_lower
  1106.         cmp al,ucase_high
  1107.         ja mn_not_lower
  1108.         mov bx,ucase_tab-ucase_low
  1109.                 cs xlatb
  1110. mn_not_lower:    stosb
  1111.         loop mn_loop            ; Don't continue if too long
  1112. mn_end:
  1113.         mov al,' '            ; Space-fill name
  1114.         rep stosb            ; Doesn't do anything if CX=0
  1115.         ret                ; Done
  1116.  
  1117. ;
  1118. ; Upper-case table for extended characters; this is technically code page 865,
  1119. ; but code page 437 users will probably not miss not being able to use the
  1120. ; cent sign in kernel images too much :-)
  1121. ;
  1122. ; The table only covers the range 129 to 164; the rest we can deal with.
  1123. ;
  1124. ucase_low    equ 129
  1125. ucase_high    equ 164
  1126. ucase_tab    db 154, 144, 'A', 142, 'A', 143, 128, 'EEEIII'
  1127.         db 142, 143, 144, 146, 146, 'O', 153, 'OUUY', 153, 154
  1128.         db 157, 156, 157, 158, 159, 'AIOU', 165
  1129.  
  1130. ;
  1131. ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
  1132. ;                filename to the conventional representation.  This is needed
  1133. ;                for the BOOT_IMAGE= parameter for the kernel.
  1134. ;                NOTE: A 13-byte buffer is mandatory, even if the string is
  1135. ;                known to be shorter.
  1136. ;
  1137. ;                DS:SI -> input mangled file name
  1138. ;                ES:DI -> output buffer
  1139. ;
  1140. ;                On return, DI points to the first byte after the output name,
  1141. ;                which is set to a null byte.
  1142. ;
  1143. unmangle_name:
  1144.                 push si                 ; Save pointer to original name
  1145.                 mov cx,8
  1146.                 mov bp,di
  1147. un_copy_body:   lodsb
  1148.                 call lower_case
  1149.                 stosb
  1150.                 cmp al,' '
  1151.                 jbe un_cb_space
  1152.                 mov bp,di               ; Position of last nonblank+1
  1153. un_cb_space:    loop un_copy_body
  1154.                 mov di,bp
  1155.                 mov al,'.'              ; Don't save
  1156.                 stosb
  1157.                 mov cx,3
  1158. un_copy_ext:    lodsb
  1159.                 call lower_case
  1160.                 stosb
  1161.                 cmp al,' '
  1162.                 jbe un_ce_space
  1163.                 mov bp,di
  1164. un_ce_space:    loop un_copy_ext
  1165.                 mov di,bp
  1166.                 mov byte [es:di], 0
  1167.                 pop si
  1168.                 ret
  1169.  
  1170. ;
  1171. ; lower_case: Lower case a character in AL
  1172. ;
  1173. lower_case:
  1174.                 cmp al,'A'
  1175.                 jb lc_ret
  1176.                 cmp al,'Z'
  1177.                 ja lc_1
  1178.                 or al,20h
  1179.                 ret
  1180. lc_1:           cmp al,lcase_low
  1181.                 jb lc_ret
  1182.                 cmp al,lcase_high
  1183.                 ja lc_ret
  1184.                 push bx
  1185.                 mov bx,lcase_tab-lcase_low
  1186.                    cs xlatb
  1187.                 pop bx
  1188. lc_ret:         ret
  1189.  
  1190. ;
  1191. ; getfssec_edx: Get multiple sectors from a file
  1192. ;
  1193. ;    This routine makes sure the subtransfers do not cross a 64K boundary,
  1194. ;    and will correct the situation if it does, UNLESS *sectors* cross
  1195. ;    64K boundaries.
  1196. ;
  1197. ;    ES:BX    -> Buffer
  1198. ;    EDX    -> Current sector number
  1199. ;    CX    -> Sector count (0FFFFh = until end of file)
  1200. ;                  Must not exceed the ES segment
  1201. ;    Returns EDX=0, CF=1 on EOF (not necessarily error)
  1202. ;    All arguments are advanced to reflect data read.
  1203. ;
  1204. getfssec_edx:
  1205.         push ebp
  1206.         push eax
  1207. .getfragment:
  1208.         xor ebp,ebp            ; Fragment sector count
  1209. .getseccnt:
  1210.         inc bp
  1211.         dec cx
  1212.         jz .do_read
  1213.         xor eax,eax
  1214.         mov ax,es
  1215.         shl ax,4
  1216.         add ax,bx            ; Now DI = how far into 64K block we are
  1217.         not ax                ; Bytes left in 64K block
  1218.         inc eax
  1219.         shr eax,SECTOR_SHIFT        ; Sectors left in 64K block
  1220.         cmp bp,ax
  1221.         jnb .do_read            ; Unless there is at least 1 more sector room...
  1222.         lea eax,[edx+1]            ; Linearly next sector
  1223.         call nextsector
  1224.         jc .do_read
  1225.         cmp edx,eax
  1226.         jz .getseccnt
  1227. .do_read:
  1228.         mov eax,edx
  1229.         call getlinsecsr
  1230.         lea eax,[eax+ebp-1]        ; This is the last sector actually read
  1231.         shl bp,9
  1232.         add bx,bp            ; Adjust buffer pointer
  1233.         call nextsector
  1234.         jc .eof
  1235.         mov edx,eax
  1236.         and cx,cx
  1237.         jnz .getfragment
  1238. .done:
  1239.         pop eax
  1240.         pop ebp
  1241.         ret
  1242. .eof:
  1243.         xor edx,edx
  1244.         stc
  1245.         jmp .done
  1246.  
  1247. ;
  1248. ; getfssec: Get multiple sectors from a file
  1249. ;
  1250. ;    Same as above, except SI is a pointer to a open_file_t
  1251. ;
  1252. ;    ES:BX    -> Buffer
  1253. ;    DS:SI    -> Pointer to open_file_t
  1254. ;    CX    -> Sector count (0FFFFh = until end of file)
  1255. ;                  Must not exceed the ES segment
  1256. ;    Returns CF=1 on EOF (not necessarily error)
  1257. ;    All arguments are advanced to reflect data read.
  1258. ;
  1259. getfssec:
  1260.         push edx
  1261.         movzx edx,cx
  1262.         cmp edx,[si+4]
  1263.         jbe .sizeok
  1264.         mov edx,[si+4]
  1265.         mov cx,dx
  1266. .sizeok:
  1267.         sub [si+4],edx
  1268.         mov edx,[si]
  1269.         call getfssec_edx
  1270.         mov [si],edx
  1271.         pop edx
  1272.         ret
  1273.  
  1274. ;
  1275. ; nextcluster: Advance a cluster pointer in EDI to the next cluster
  1276. ;           pointed at in the FAT tables.  CF=0 on return if end of file.
  1277. ;
  1278. nextcluster:
  1279.         jmp strict short nextcluster_fat28    ; This gets patched
  1280.  
  1281. nextcluster_fat12:
  1282.         push eax
  1283.         push edx
  1284.         push bx
  1285.         push cx
  1286.         push si
  1287.         mov edx,edi
  1288.         shr edi,1
  1289.         pushf            ; Save the shifted-out LSB (=CF)
  1290.         add edx,edi
  1291.         mov eax,edx
  1292.         shr eax,9
  1293.         call getfatsector
  1294.         mov bx,dx
  1295.         and bx,1FFh
  1296.         mov cl,[gs:si+bx]
  1297.         inc edx
  1298.         mov eax,edx
  1299.         shr eax,9
  1300.         call getfatsector
  1301.         mov bx,dx
  1302.         and bx,1FFh
  1303.         mov ch,[gs:si+bx]
  1304.         popf
  1305.         jnc .even
  1306.         shr cx,4
  1307. .even:        and cx,0FFFh
  1308.         movzx edi,cx
  1309.         cmp di,0FF0h
  1310.         pop si
  1311.         pop cx
  1312.         pop bx
  1313.         pop edx
  1314.         pop eax
  1315.         ret
  1316.  
  1317. ;
  1318. ; FAT16 decoding routine.
  1319. ;
  1320. nextcluster_fat16:
  1321.         push eax
  1322.         push si
  1323.         push bx
  1324.         mov eax,edi
  1325.         shr eax,SECTOR_SHIFT-1
  1326.         call getfatsector
  1327.         mov bx,di
  1328.         add bx,bx
  1329.         and bx,1FEh
  1330.         movzx edi,word [gs:si+bx]
  1331.         cmp di,0FFF0h
  1332.         pop bx
  1333.         pop si
  1334.         pop eax
  1335.         ret
  1336. ;
  1337. ; FAT28 ("FAT32") decoding routine.
  1338. ;
  1339. nextcluster_fat28:
  1340.         push eax
  1341.         push si
  1342.         push bx
  1343.         mov eax,edi
  1344.         shr eax,SECTOR_SHIFT-2
  1345.         call getfatsector
  1346.         mov bx,di
  1347.         add bx,bx
  1348.         add bx,bx
  1349.         and bx,1FCh
  1350.         mov edi,dword [gs:si+bx]
  1351.         and edi,0FFFFFFFh    ; 28 bits only
  1352.         cmp edi,0FFFFFF0h
  1353.         pop bx
  1354.         pop si
  1355.         pop eax
  1356.         ret
  1357.  
  1358. ;
  1359. ; nextsector:    Given a sector in EAX on input, return the next sector
  1360. ;             of the same filesystem object, which may be the root
  1361. ;                  directory or a cluster chain.  Returns  EOF.
  1362. ;
  1363. ;              Assumes CS == DS.
  1364. ;
  1365. nextsector:
  1366.         push edi
  1367.         push edx
  1368.         mov edx,[DataArea]
  1369.         mov edi,eax
  1370.         sub edi,edx
  1371.         jae .isdata
  1372.  
  1373.         ; Root directory
  1374.         inc eax
  1375.         cmp eax,edx
  1376.         cmc
  1377.         jmp .done
  1378.  
  1379. .isdata:
  1380.         not edi
  1381.         test edi,[ClustMask]
  1382.         jz .endcluster
  1383.  
  1384.         ; It's not the final sector in a cluster
  1385.         inc eax
  1386.         jmp .done
  1387.  
  1388. .endcluster:
  1389.         push gs            ; nextcluster trashes gs
  1390.         push cx
  1391.         not edi
  1392.         mov cl,[ClustShift]
  1393.         shr edi,cl
  1394.         add edi,2
  1395.  
  1396.         ; Now EDI contains the cluster number
  1397.         call nextcluster
  1398.         cmc
  1399.         jc .exit        ; There isn't anything else...
  1400.  
  1401.         ; New cluster number now in EDI
  1402.         sub edi,2
  1403.         shl edi,cl        ; CF <- 0, unless something is very wrong
  1404.         lea eax,[edi+edx]
  1405. .exit:
  1406.         pop cx
  1407.         pop gs
  1408. .done:
  1409.         pop edx
  1410.         pop edi
  1411.         ret
  1412.  
  1413. ;
  1414. ; getfatsector: Check for a particular sector (in EAX) in the FAT cache,
  1415. ;        and return a pointer in GS:SI, loading it if needed.
  1416. ;
  1417. ;        Assumes CS == DS.
  1418. ;
  1419. getfatsector:
  1420.         add eax,[FAT]        ; FAT starting address
  1421.         jmp getcachesector
  1422.  
  1423. ; -----------------------------------------------------------------------------
  1424. ;  Common modules
  1425. ; -----------------------------------------------------------------------------
  1426.  
  1427. %include "getc.inc"        ; getc et al
  1428. %include "conio.inc"        ; Console I/O
  1429. %include "writestr.inc"        ; String output
  1430. %include "parseconfig.inc"    ; High-level config file handling
  1431. %include "parsecmd.inc"        ; Low-level config file handling
  1432. %include "bcopy32.inc"        ; 32-bit bcopy
  1433. %include "loadhigh.inc"        ; Load a file into high memory
  1434. %include "font.inc"        ; VGA font stuff
  1435. %include "graphics.inc"        ; VGA graphics
  1436. %include "highmem.inc"        ; High memory sizing
  1437. %include "strcpy.inc"           ; strcpy()
  1438. %include "cache.inc"        ; Metadata disk cache
  1439.  
  1440. ; -----------------------------------------------------------------------------
  1441. ;  Begin data section
  1442. ; -----------------------------------------------------------------------------
  1443.  
  1444.         section .data
  1445. ;
  1446. ; Lower-case table for codepage 865
  1447. ;
  1448. lcase_low       equ 128
  1449. lcase_high      equ 165
  1450. lcase_tab       db 135, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138
  1451.                 db 139, 140, 141, 132, 134, 130, 145, 145, 147, 148, 149
  1452.                 db 150, 151, 152, 148, 129, 155, 156, 155, 158, 159, 160
  1453.                 db 161, 162, 163, 164, 164
  1454.  
  1455. copyright_str   db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
  1456.         db CR, LF, 0
  1457. boot_prompt    db 'boot: ', 0
  1458. wipe_char    db BS, ' ', BS, 0
  1459. err_notfound    db 'Could not find kernel image: ',0
  1460. err_notkernel    db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
  1461. err_noram    db 'It appears your computer has less than '
  1462.         asciidec dosram_k
  1463.         db 'K of low ("DOS")'
  1464.         db CR, LF
  1465.         db 'RAM.  Linux needs at least this amount to boot.  If you get'
  1466.         db CR, LF
  1467.         db 'this message in error, hold down the Ctrl key while'
  1468.         db CR, LF
  1469.         db 'booting, and I will take your word for it.', CR, LF, 0
  1470. err_badcfg      db 'Unknown keyword in syslinux.cfg.', CR, LF, 0
  1471. err_noparm      db 'Missing parameter in syslinux.cfg.', CR, LF, 0
  1472. err_noinitrd    db CR, LF, 'Could not find ramdisk image: ', 0
  1473. err_nohighmem   db 'Not enough memory to load specified kernel.', CR, LF, 0
  1474. err_highload    db CR, LF, 'Kernel transfer failure.', CR, LF, 0
  1475. err_oldkernel   db 'Cannot load a ramdisk with an old kernel image.'
  1476.                 db CR, LF, 0
  1477. err_notdos    db ': attempted DOS system call', CR, LF, 0
  1478. err_comlarge    db 'COMBOOT image too large.', CR, LF, 0
  1479. err_a20        db CR, LF, 'A20 gate not responding!', CR, LF, 0
  1480. err_bootfailed    db CR, LF, 'Boot failed: please change disks and press '
  1481.         db 'a key to continue.', CR, LF, 0
  1482. ready_msg    db 'Ready.', CR, LF, 0
  1483. crlfloading_msg    db CR, LF
  1484. loading_msg     db 'Loading ', 0
  1485. dotdot_msg      db '.'
  1486. dot_msg         db '.', 0
  1487. aborted_msg    db ' aborted.'            ; Fall through to crlf_msg!
  1488. crlf_msg    db CR, LF
  1489. null_msg    db 0
  1490. crff_msg    db CR, FF, 0
  1491. syslinux_cfg    db 'SYSLINUXCFG'        ; Mangled form
  1492. ConfigName    db 'syslinux.cfg',0        ; Unmangled form
  1493. %if IS_MDSLINUX
  1494. manifest    db 'MANIFEST   '
  1495. %endif
  1496. ;
  1497. ; Command line options we'd like to take a look at
  1498. ;
  1499. ; mem= and vga= are handled as normal 32-bit integer values
  1500. initrd_cmd    db 'initrd='
  1501. initrd_cmd_len    equ 7
  1502.  
  1503. ;
  1504. ; Config file keyword table
  1505. ;
  1506. %include "keywords.inc"
  1507.  
  1508. ;
  1509. ; Extensions to search for (in *forward* order).
  1510. ;
  1511. exten_table:    db 'CBT',0        ; COMBOOT (specific)
  1512.         db 'BSS',0        ; Boot Sector (add superblock)
  1513.         db 'BS ',0        ; Boot Sector 
  1514.         db 'COM',0        ; COMBOOT (same as DOS)
  1515.         db 'C32',0        ; COM32
  1516. exten_table_end:
  1517.         dd 0, 0            ; Need 8 null bytes here
  1518.  
  1519. ;
  1520. ; Misc initialized (data) variables
  1521. ;
  1522. %ifdef debug                ; This code for debugging only
  1523. debug_magic    dw 0D00Dh        ; Debug code sentinel
  1524. %endif
  1525.  
  1526.         alignb 4, db 0
  1527. BufSafe        dw trackbufsize/SECTOR_SIZE    ; Clusters we can load into trackbuf
  1528. BufSafeSec    dw trackbufsize/SECTOR_SIZE    ; = how many sectors?
  1529. BufSafeBytes    dw trackbufsize        ; = how many bytes?
  1530. EndOfGetCBuf    dw getcbuf+trackbufsize    ; = getcbuf+BufSafeBytes
  1531. %ifndef DEPEND
  1532. %if ( trackbufsize % SECTOR_SIZE ) != 0
  1533. %error trackbufsize must be a multiple of SECTOR_SIZE
  1534. %endif
  1535. %endif
  1536.